package net.onceface.web.oauth2;

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;

public class LoginAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider{

	private CustomPasswordEncoder passwordEncoder = new CustomPasswordEncoder();  
	  
    private SaltSource saltSource;  
  
    private UserService userService;  
    
    private String userNotFoundEncodedPassword;
    
    /**
     * 密码认证逻辑，判断输入的密码与数据库密码是否匹配
     * 是否盐值加密和加密次数在配置文件中配置
     * **/
	@Override
	protected void additionalAuthenticationChecks(UserDetails userDetails,
			UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		// TODO Auto-generated method stub
		Object salt = null;  
		 
        if (this.saltSource != null){  
            salt = this.saltSource.getSalt(userDetails);  
            salt += userDetails.getUsername();
        }  
        if (authentication.getCredentials() == null){
        	logger.debug("Authentication failed: no credentials provided");
        	throw new BadCredentialsException("Bad credentials:" + userDetails);
        }
        String presentedPassword = authentication.getCredentials().toString(); 
        if (!passwordEncoder.isPasswordValid(userDetails.getPassword(), presentedPassword, salt)){
        	logger.debug("Authentication failed: password does not match stored value");  
        	throw new BadCredentialsException("Bad credentials:" + userDetails);
        } 
	}

	protected void doAfterPropertiesSet() throws Exception {
		Assert.notNull(this.userService, "A UserDetailsService must be set");
	}
	
	protected CustomPasswordEncoder getPasswordEncoder(){
		return passwordEncoder;  
	}
	public void setPasswordEncoder(CustomPasswordEncoder passwordEncoder){
		this.passwordEncoder = passwordEncoder;  
	}
	protected SaltSource getSaltSource()  {
		return saltSource; 
	}
	public void setSaltSource(SaltSource saltSource)  {
		this.saltSource = saltSource; 
	}
	
	protected UserService getUserService() {
		return userService;
	}
	public void setUserService(UserService userService) {
		this.userService = userService;
	}
	/**
	 * 按用户名查询可用的用户
	 * **/
	@Override
	protected UserDetails retrieveUser(String username,UsernamePasswordAuthenticationToken authentication)
			throws AuthenticationException {
		// TODO Auto-generated method stub
		UserDetails loadedUser; 
		try{
			//String password = (String) authentication.getCredentials(); 
			loadedUser = getUserService().loadUserByUsername(username);
			
		}catch (UsernameNotFoundException notFound) {
			if (authentication.getCredentials() != null) {
				String presentedPassword = authentication.getCredentials().toString();
				passwordEncoder.isPasswordValid(userNotFoundEncodedPassword,
						presentedPassword, null);
			}
			throw notFound;
		}catch (Exception repositoryProblem) {
			throw new InternalAuthenticationServiceException(
					repositoryProblem.getMessage(), repositoryProblem);
		}
		if (loadedUser == null) {
			throw new InternalAuthenticationServiceException(
					"UserDetailsService returned null, which is an interface contract violation");
		}
		return loadedUser;
	}

}
